package com.treasure.mall.biz.service.core.auction.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.AuctionBidCondition;
import com.treasure.mall.biz.entity.auction.AuctionBidPO;
import com.treasure.mall.biz.entity.auction.AuctionBidPO_;
import com.treasure.mall.biz.entity.auction.AuctionSessionPO_;
import com.treasure.mall.biz.entity.user.UserPO_;
import com.treasure.mall.biz.repository.auction.AuctionBidRepository;
import com.treasure.mall.biz.service.core.auction.AuctionBidService;
import com.treasure.mall.zbq.common.ienum.auction.AuctionEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/7/16
 */
@Service
public class AuctionBidServiceImpl extends AbstractSearchableCrudService<AuctionBidPO, Long> implements AuctionBidService {
    private AuctionBidRepository bidRepository;

    @Autowired
    protected AuctionBidServiceImpl(AuctionBidRepository repository) {
        super(repository);
        this.bidRepository = repository;
    }

    @Override
    protected SpecificationAndSort<AuctionBidPO> specificationAndSort(BaseSearchDTO searchDTO) {
        AuctionBidCondition condition = (AuctionBidCondition) searchDTO;

        Specification<AuctionBidPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (condition.getStatus() != -1) {
                switch (condition.getStatus()) {
                    case 0:
                        predicates.add(cb.equal(root.get(AuctionBidPO_.sessionPO).get(AuctionSessionPO_.AUCTION_STATUS), AuctionEnums.AuctionStatus.IN_AUCTION));
                        break;
                    case 1:
                        predicates.add(cb.equal(root.get(AuctionBidPO_.sessionPO).get(AuctionSessionPO_.AUCTION_STATUS), AuctionEnums.AuctionStatus.END));
                        predicates.add(cb.isTrue(root.get(AuctionBidPO_.success)));
                        break;
                    default:
                        predicates.add(cb.equal(root.get(AuctionBidPO_.sessionPO).get(AuctionSessionPO_.AUCTION_STATUS), AuctionEnums.AuctionStatus.END));
                        predicates.add(cb.isFalse(root.get(AuctionBidPO_.success)));
                        break;
                }
            }
            if (condition.getUserId() > 0) {
                predicates.add(cb.equal(root.get(AuctionBidPO_.userPO).get(UserPO_.userId), condition.getUserId()));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public AuctionBidPO findWinner(Long sessionId) {
        return bidRepository.findBySessionPO_IdAndSuccessIsTrue(sessionId);
    }

    @Override
    public List<AuctionBidPO> findLosers(Long sessionId) {
        return bidRepository.findBySessionPO_IdAndSuccessIsFalse(sessionId);
    }

    @Override
    public AuctionBidPO findByUserAndSession(Long userId, Long sessionId) {
        return bidRepository.findBySessionPO_IdAndUserPO_UserId(sessionId, userId);
    }

    @Override
    public Page<AuctionBidPO> findBySessionId(Long sessionId, int pageIndex, int pageSize) {
        return bidRepository.findBySessionPO_IdOrderByBidAmountDesc(sessionId, PageRequest.of(pageIndex - 1, pageSize));
    }

    @Override
    public AuctionBidPO save(BaseSaveDTO saveDTO) {
        return null;
    }
}
